﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework;

namespace Blockey.GameObjects3D
{
    public class DrawableModel : DrawableObject
    {
        public DrawableModel(GraphicsDevice oGraphics, ContentManager oManager, string oModelPath, bool oLighting)
        {
            m_bLighting = oLighting;
            m_oModel = oManager.Load<Model>(oModelPath);
            m_mWorld = Matrix.Identity;

            m_mTransforms = new Matrix[m_oModel.Bones.Count];
            m_oModel.CopyAbsoluteBoneTransformsTo(m_mTransforms);

            m_oEffect = oManager.Load<Effect>("Effects\\PointLight");

            var oMaterial = new PointLightMaterial();
            oMaterial.LightPosition = new Vector3(0, 0, 40);

            foreach (ModelMesh mesh in m_oModel.Meshes)
            {
                foreach (ModelMeshPart part in mesh.MeshParts)
                {
                    //var oEffect = m_oEffect;
                    var oBasicEffect = part.Effect as BasicEffect;
                    Vector3 oDiffuseColor = Vector3.One;

                    if (oBasicEffect != null)
                    {
                        oDiffuseColor = oBasicEffect.DiffuseColor;
                    }

                    part.Effect = m_oEffect;

                    if (oDiffuseColor != Vector3.One)
                    {
                        part.Effect.Parameters["DiffuseColor"].SetValue(oDiffuseColor);
                    }
                }
            }

            SetTransformation(Vector3.Zero, new Vector3(MathHelper.PiOver2, 0, 0), 1f);

            Material = oMaterial;
        }

        public override void Draw(GraphicsDevice oGraphics, Camera3D oCamera)
        {
            m_mTransforms = new Matrix[m_oModel.Bones.Count];
            m_oModel.CopyAbsoluteBoneTransformsTo(m_mTransforms);

            //Material.SetEffectParameters(m_oEffect);

            var oWorld =
                        Matrix.CreateScale(m_fScale) *
                        Matrix.CreateRotationX(m_vRotation.X) *
                        Matrix.CreateRotationY(m_vRotation.Y) *
                        Matrix.CreateRotationZ(m_vRotation.Z) *
                        Matrix.CreateTranslation(m_vTranslation);

            foreach (ModelMesh mesh in m_oModel.Meshes)
            {
                foreach (var oPart in mesh.MeshParts)
                {
                    oPart.Effect.Parameters["View"].SetValue(oCamera.View);
                    oPart.Effect.Parameters["Projection"].SetValue(oCamera.Projection);
                    oPart.Effect.Parameters["World"].SetValue(oWorld * m_mTransforms[mesh.ParentBone.Index]);
                    Material.SetEffectParameters(oPart.Effect);
                }
                mesh.Draw();
            }
        }

        public override void SetTexture(Texture2D oTexture)
        {
            foreach (ModelMesh mesh in m_oModel.Meshes)
            {
                foreach (BasicEffect oEffect in mesh.Effects)
                {
                    oEffect.Texture = oTexture;
                    oEffect.TextureEnabled = true;
                }
            }
        }

        protected override void SetSphere()
        {
            for (int i = 0; i < m_oModel.Meshes.Count; i++)
            {
                if (i == 0)
                    m_oSphere = m_oModel.Meshes[i].BoundingSphere;
                else
                    m_oSphere = BoundingSphere.CreateMerged(m_oSphere, m_oModel.Meshes[i].BoundingSphere);
            }
        }

        private bool m_bLighting;
        private Matrix[] m_mTransforms;
        protected Model m_oModel;

    }
}
